package main

import (
	"fmt"
	"time"
)

func main() {
	fmt.Println("Hello, world!")
	multiChannel()
}

// channel 判断是否关闭
func oneChannel() {
	ch := make(chan int)

	go func() {
		for i := 0; i < 10; i++ {
			fmt.Println("ch <- i")
			ch <- i
		}
		close(ch)
	}()

	for i := 0; i < 12; i++ {
		v, ok := <-ch
		if ok {
			fmt.Println(v)
		}
	}

}

func multiChannel() {
	// 创建一个容量为 1 的缓冲 channel
	bufferedCh := make(chan int, 5)

	// 启动生产者 goroutine
	go func() {
		for i := 1; i <= 30; i++ {
			fmt.Printf("Producer: Sending %d\n", i)
			bufferedCh <- i             // 如果缓冲区已满，发送操作将阻塞
			time.Sleep(1 * time.Second) // 模拟生产时间
		}
		close(bufferedCh) // 发送完成后关闭 channel
	}()

	// 启动消费者 goroutine
	go func() {
		for val := range bufferedCh {
			fmt.Printf("Consumer: Received %d\n", val)
			time.Sleep(2 * time.Second) // 模拟消费时间，比生产时间长
		}
	}()

	// 主 goroutine 等待一段时间，以便其他 goroutine 完成工作
	time.Sleep(10 * time.Second) // 等待足够长的时间以观察输出
}

// select 语句用于在多个 channel 上等待操作，并选择一个可以立即执行的 case 分支。它提供了一种非阻塞的方式来处理多个 channel 的读写操作。
func selectChannel() {
	// 创建两个 channel
	ch1 := make(chan string)
	ch2 := make(chan string)

	// 启动一个 goroutine，向 ch1 发送数据
	go func() {
		for i := 0; i < 10; i++ {
			time.Sleep(1 * time.Second) // 模拟一些处理时间
			ch1 <- "Message from ch1"
		}

	}()

	// 启动另一个 goroutine，向 ch2 发送数据
	go func() {
		for i := 0; i < 12; i++ {
			time.Sleep(2 * time.Second) // 模拟一些处理时间
			ch2 <- "Message from ch2"
		}

	}()

	// 使用 select 语句监听多个 channel
	for i := 0; i < 200; i++ { // 假设我们知道会有两个消息，或者可以用其他条件终止循环
		select {
		case msg1 := <-ch1:
			fmt.Println("Received:", msg1)
		case msg2 := <-ch2:
			fmt.Println("Received:", msg2)
		default:
			// 如果没有任何 channel 准备好，可以执行默认操作（可选）
			fmt.Println("No message received, waiting...")
			time.Sleep(200 * time.Millisecond) // 防止忙等待
		}
	}
}
